/*
 * PostgresqQuery object defines the needed query functions for the dbConnect PostgreSQL driver
 * Copyright (C) 2003 Johnathan Ingram, jingram@rogueware.org
 *
 * This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Lesser General Public
 *   License as published by the Free Software Foundation; either
 *   version 2.1 of the License, or (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with this library; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  US
 *
 */


#ifndef __PGSQL_QUERY_H__
#define __PGSQL_QUERY_H__


#include "baseQuery.h"
#include "baseFieldDescription.h"

#include "pgsqlConnection.h"
#include "pgsqlBindParam.h"
#include "pgsqlValue.h"


using namespace std;

class PostgresqlQuery : public BaseQuery
{

private:  
   // Collection types that can be freed within this object
   enum CollectionType
   {
      FIELD_INFORMATION,
      FIELD_VALUES,
      BIND_PARAMETERS
   };

   // PostgreSQL Handles
   PGresult         *__pgsql_res__;
   DBULONG          _pgsqlNumRows;
   DBULONG          _pgsqlCurrentRow;

   // Parameter collection.
   DBULONG               _numParameters;
   PostgresqlBindParam **_parameters;

   // Field Information collection
   DBULONG                _numFieldInformation;
   BaseFieldDescription **_fieldInformation;

   // Field Value collection
   DBULONG           _numRecordValues;
   PostgresqlValue **_recordValues;

   
   PostgresqlConnection* _parentConnection;
   int                   _index;            // Index of the handle object
   bool                  _isTransaction;    // Is the object in a state of a transaction running.

   /* Internal method to obtain the information 
    *   about the fields returned in a result set.
    */
   void
   _pgsqlGetFieldsInformation();


   /* Internal method to obtain the data in the result set row
    */
   void
   _pgsqlGetResultSetRow();


   /* Internal method to return the dbConnect type for the postgreSQL field
    *
    * @param type    The PostgreSQL field type to resolve to a dbConnect field type
    *
    * @return   Returns the dbConnect field type for the given PostgreSQL field type
    */
   FieldType
   _pgsqlResolveFieldType(
      Oid type);


   /* Internal method to parse the parameters that need to be bound in the SQL query
    *
    * @param originalSqlStatement  The sql statement with the bind parameters.
    *
    * @return   Returns the parsed SQL that can be executed by PostgreSQL
    */
   string
   _pgsqlParseBindParameters(
         const string& originalSqlStatement);


   /* Internal method to check if a function/procedure is to be called
    * and to build the correct SQL function call if it is
    *
    * @param originalSqlStatement  The sql statement WITHOUT the bind parameters.
    *
    * @return   Returns the new SQL if it is a function or the original SQL if it is not a function
    */
   string
   _pgsqlParseFunctionCall(
         const string& originalSqlStatement);


   /* Internal method to free internally allocated memory
    *
    * @param type    The type representing which value to deallocate.
    *
    */
   void _freeCollection(
      CollectionType type);
   
public:

   /* Constructor.
    *
    */
   PostgresqlQuery(
      PostgresqlConnection* parentConnection,
      int                   index);


   /* Destructor.
    *
    */
   virtual 
   ~PostgresqlQuery();
   

   /* Clears any bind parameters
    *
    */
   void 
   clearBindParams();


   /* Set the SQL / DDL command that will be used for bind 
    *  paramaters and the execute
    *
    * @param sqlStatement  Statement wanting to execute
    *
    */
   void
   command(
      const string& sqlStatement);


   /* Set the value for a parameter giving the parameter name.
    *
    * @param paramName      Name of the parameter.
    *
    * @return               Returns the parameter object for the position.
    */
   BaseValue*
   bindParam(
      const string& paramName);


   /* Execute the sql statement set by command
    *
    */
   void
   execute();


   /* Obtain the next row of data in the record set.
    *
    */
   void
   fetchNext();


   /* Begin a transaction.
    * Make virtual so a new driver can inherit and implement
    *
    */
   virtual void
   transBegin();
   
   
   /* Commit a transaction.
    * Make virtual so a new driver can inherit and implement
    *
    */
   virtual void
   commit();
   
   
   /* Rollback a transaction.
    * Make virtual so a new driver can inherit and implement
    *
    */
   virtual void
   rollback();   


   /* Returns the information about a field.
    *
    * @param    index     Index of the field.
    *
    * @return             Returns a pointer to the field information structure.
    */
   BaseFieldDescription*
   getFieldInfoByColumn(
      int index);


   /* Returns the information about a field.
    *
    * @param    fieldName Name of the field.
    *
    * @return             Returns a pointer to the field information structure.
    */
   BaseFieldDescription*
   getFieldInfoByName(
      const string& fieldName);
      
   /* Returns the value of a field.
    *
    * @param    index     Index of the field.
    *
    * @return   Returns a pointer to the value structure.
    */
   BaseValue*
   getFieldByColumn(
      int index);


   /* Returns the value of a field.
    *
    * @param    fieldName Name of the field.
    *
    * @return   Returns a pointer to the value structure.
    */
   BaseValue*
   getFieldByName(
      const string& fieldName);

};

#endif
